#pragma once
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "ThreadPool.hpp"

using namespace LogMudule;
using namespace ThreadPoolModual;

const static uint16_t defaultport = 8888;

using task_t = std::function<void()>;
using command_t = std::function<std::string(const std::string)>;

class TCPSever
{
    // 1.目前是一个EchoSever,单进程版
    // void Service(int sockfd)
    // {
    //     char buff[1024];
    //     while(true)
    //     {
    //         //TCP是面向字节流的，故而可以采用文件的接口进行读取和写入
    //         int n=::read(sockfd,buff,sizeof(buff)-1);
    //         if(n>0)
    //         {
    //             buff[n]=0;
    //             std::string message="Client Say@";
    //             message+=buff;
    //             int m=::write(sockfd,message.c_str(),message.size());
    //             if(m<0)
    //             {
    //                 LOG(LogLevel::ERROR)<<"write failed";
    //             }
    //         }
    //         else if(n==0)
    //         {
    //             //表示读到了文件末尾
    //             LOG(LogLevel::INFO)<<"Client Quit……";
    //             break;
    //         }
    //         else
    //         {
    //             LOG(LogLevel::ERROR)<<"read error";
    //             break;
    //         }
    //     }
    // }

    // // 2.进程分离
    // void Service(int sockfd)
    // {
    //     char buff[1024];
    //     while (true)
    //     {

    //         // TCP是面向字节流的，故而可以采用文件的接口进行读取和写入
    //         int n = ::read(sockfd, buff, sizeof(buff) - 1);
    //         if (n > 0)
    //         {
    //             buff[n] = 0;
    //             std::string message = "Client Say@";
    //             message += buff;
    //             int m = ::write(sockfd, message.c_str(), message.size());
    //             if (m < 0)
    //             {
    //                 LOG(LogLevel::ERROR) << "write failed";
    //             }
    //         }
    //         else if (n == 0)
    //         {
    //             // 表示读到了文件末尾
    //             LOG(LogLevel::INFO) << "Client Quit……";
    //             break;
    //         }
    //         else
    //         {
    //             LOG(LogLevel::ERROR) << "read error";
    //             break;
    //         }
    //     }
    // }
    // // 3. 线程分离管理
    // struct ThreadData
    // {
    //     int _sockfd;
    //     TCPSever *_self;
    // };
    // static void *Handler(void *args)
    // {
    //     pthread_detach(pthread_self());
    //     ThreadData *data = (ThreadData *)args;
    //     data->_self->Service(data->_sockfd);
    //     return nullptr;
    // }
    // 5.远程命令执行
    void Service(int sockfd)
    {
        char buff[1024];
        while (true)
        {

            // TCP是面向字节流的，故而可以采用文件的接口进行读取和写入
            int n = ::read(sockfd, buff, sizeof(buff) - 1);
            if (n > 0)
            {
                //网络传输中以\r\n结尾
                buff[n-2] = 0;
                
                std::string message = _command(buff);
                int m = ::send(sockfd, message.c_str(), message.size(),0);
                if (m < 0)
                {
                    LOG(LogLevel::ERROR) << "write failed";
                }
            }
            else if (n == 0)
            {
                // 表示读到了文件末尾
                LOG(LogLevel::INFO) << "Client Quit……";
                break;
            }
            else
            {
                LOG(LogLevel::ERROR) << "read error";
                break;
            }
        }
    }

public:
    TCPSever(command_t command, uint16_t port = defaultport) : _command(command), _addr(port)
    {
        // 创建套接字
        int n = _listensockfd = ::socket(AF_INET, SOCK_STREAM, 0);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "socket failed";
            exit(1);
        }
        LOG(LogLevel::INFO) << "socket succeed";
        // 绑定
        n = ::bind(_listensockfd, _addr.NetAddr(), _addr.Len());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind failed";
            exit(1);
        }
        LOG(LogLevel::INFO) << "bind succeed";
        // 开始监听
        n = ::listen(_listensockfd, 5);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "listen failed";
            exit(1);
        }
        LOG(LogLevel::INFO) << "listen succeed";
    }

    void Run()
    {
        while (true)
        {
            // 1.单进程版本的
            // //获取连接
            // struct sockaddr_in connected_addr;
            // socklen_t len=sizeof(connected_addr);
            // int sockfd=::accept(_listensockfd,(struct sockaddr*)&connected_addr,&len);
            // if(sockfd<0)
            // {
            //     LOG(LogLevel::ERROR)<<"accept failed";
            //     continue;
            // }

            // InetAddr peer(connected_addr);
            // LOG(LogLevel::INFO)<<"accept succeed connected is "<<peer.Addr() <<" sockfd is "<<sockfd;

            // //既然可以获取到信息了，那么下一步就是提供服务了
            // Service(sockfd);

            // //完成之后就要关闭sockfd
            // ::close(sockfd);

            // // 2. 进程分离版本
            // // 获取连接
            // struct sockaddr_in connected_addr;
            // socklen_t len = sizeof(connected_addr);
            // int sockfd = ::accept(_listensockfd, (struct sockaddr *)&connected_addr, &len);
            // if (sockfd < 0)
            // {
            //     LOG(LogLevel::ERROR) << "accept failed";
            //     continue;
            // }

            // InetAddr peer(connected_addr);
            // LOG(LogLevel::INFO) << "accept succeed connected is " << peer.Addr() << " sockfd is " << sockfd;
            // int id = fork();
            // if (id == 0)
            // {
            //     // 子进程
            //     ::close(_listensockfd);
            //     // 子进程再次创建子进程，子进程返回，避免父进程阻塞，孙子进程为孤儿进程，被OS领养
            //     if(fork()>0)    exit(0);
            //     Service(sockfd);
            //     exit(0);
            // }
            // else
            // {
            //     // 父进程
            //     ::close(sockfd);
            //     int rid=::waitpid(id,nullptr,0);
            //     if(rid<0)
            //     {
            //         LOG(LogLevel::ERROR) << "waitpid failed";
            //     }
            // }
            // 3.线程管理版本的
            // 获取连接
            // struct sockaddr_in connected_addr;
            // socklen_t len = sizeof(connected_addr);
            // int sockfd = ::accept(_listensockfd, (struct sockaddr *)&connected_addr, &len);
            // if (sockfd < 0)
            // {
            //     LOG(LogLevel::ERROR) << "accept failed";
            //     continue;
            // }

            // InetAddr peer(connected_addr);
            // LOG(LogLevel::INFO) << "accept succeed connected is " << peer.Addr() << " sockfd is " << sockfd;

            // ThreadData *data = new ThreadData;
            // data->_sockfd = sockfd;
            // data->_self = this;

            // pthread_t tid;
            // pthread_create(&tid, nullptr, Handler, data);
            // // 4.线程池管理版本
            // struct sockaddr_in connected_addr;
            // socklen_t len = sizeof(connected_addr);
            // int sockfd = ::accept(_listensockfd, (struct sockaddr *)&connected_addr, &len);
            // if (sockfd < 0)
            // {
            //     LOG(LogLevel::ERROR) << "accept failed";
            //     continue;
            // }

            // InetAddr peer(connected_addr);
            // LOG(LogLevel::INFO) << "accept succeed connected is " << peer.Addr() << " sockfd is " << sockfd;

            // //绑定生成任务
            // task_t task=std::bind(&TCPSever::Service,this,sockfd);
            // ThreadPool<task_t> ::GetInstance()->Enqueue(task);
            // 4.远程执行任务
            struct sockaddr_in connected_addr;
            socklen_t len = sizeof(connected_addr);
            int sockfd = ::accept(_listensockfd, (struct sockaddr *)&connected_addr, &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::ERROR) << "accept failed";
                continue;
            }

            InetAddr peer(connected_addr);
            LOG(LogLevel::INFO) << "accept succeed connected is " << peer.Addr() << " sockfd is " << sockfd;

            // 绑定生成任务
            task_t task = std::bind(&TCPSever::Service, this, sockfd);
            ThreadPool<task_t>::GetInstance()->Enqueue(task);
        }
    }
    ~TCPSever()
    {
        ::close(_listensockfd);
    }

private:
    int _listensockfd;
    InetAddr _addr;

    command_t _command;
};
